<?php
/**
 * 读取配置文件中的配置
 * 
 * @version $Id: IConfig.php 323 2008-05-14 05:49:20Z iwind $
 * @package util.core
 */
class IConfig extends IObject {
	private static $mvcConfig;
	private static $config;
	private static $configFile;
	private static $serverConfig = array();
	
	/**
	 * 加载配置文件
	 *
	 * @param string $configXml 配置文件
	 * @deprecated 
	 */
	public static function loadConfigXml($configXml) {
		$configXml;
	}
	
	/**
	 * 取得server短配置对应表
	 * 
	 * 即iframework-web.conf中的配置选项，形如：
	 * Array
	 * (
	 *     [server] => Array
	 *         (
	 *             [server.name] => localhost
	 *             [server.environment] => test
	 *         )
	 * 
	 * )
	 *
	 * @return array
	 */
	public static function getServerConfigMap() {
		if (!empty(self::$serverConfig)) {
			return self::$serverConfig;
		}
		if (isset(self::$config["server"]["config"])) {
			$configFile = self::$config["server"]["config"];
			if ($configFile == "") {
				return array();
			}
			if (!native::isAbsolutePath($configFile)) {
				$configFile = IFRAMEWORK_APP_ROOT . "/" . $configFile;
			}
			if (!is_file($configFile)) {
				throw new IException("can't find server config file '{$configFile}'");
			}
			self::$serverConfig = parse_ini_file($configFile, true);
			return self::$serverConfig;
		}
		return array();
	}
	
	/**
	 * 取得选项的值
	 * 
	 * 将会在应用配置列表和$_CONFIG全局变量中查找
	 *
	 * @param string $option 选项名称
	 * @return mixed
	 */
	public static function getOptionValue($option) {
		global $_CONFIG;
		if (is_array($_CONFIG) && array_key_exists($option, $_CONFIG)) {
			return $_CONFIG[$option];
		}
		else if(array_key_exists($option, self::$config)) {
			return self::$config[$option];
		}
		return null;
	}
	
	/**
	 * 取得选项的值
	 * 
	 * 是getOptionValue的同义词
	 *
	 * @param string $option 选项名称
	 * @return mixed
	 * @since 0.2.1
	 * @see getOptionValue
	 */
	public static function getOption($option) {
		return self::getOptionValue($option);
	}
	
	/**
	 * 取得server名称
	 *
	 * @return string
	 */
	public static function getServerName() {
		$serverConfig = self::getServerConfigMap();
		if (isset($serverConfig["server"]["server.name"])) {
			return $serverConfig["server"]["server.name"];
		}
		return null;
	}
	
	/**
	 * 取得server环境
	 * 
	 * 一般为development,test和production其中的一种
	 *
	 * @return string
	 */
	public static function getServerEnvironment() {
		$serverConfig = self::getServerConfigMap();
		if (isset($serverConfig["server"]["server.environment"])) {
			return $serverConfig["server"]["server.environment"];
		}
		return null;
	}
	
	/**
	 * 取得日志级别
	 *
	 * @return integer
	 */
	public static function getLoggerLevel() {
		if (isset(self::$config["logger"]["level"])) {
			return intval(self::$config["logger"]["level"]);
		}
		return ILogger::LOGGER_FATAL;
	}
	
	/**
	 * 添加新的路径到class path
	 * 
	 * 可以使用逗号（,）隔开多个路径
	 *
	 * @param string $classPath  新的class目录
	 */
	public static function addClassPath($classPath) {
		$paths = explode(",", $classPath);
		foreach ($paths as $path) {
			self::$config["class-path"][] = $path;
		}
	}
	
	/**
	 * 取得class path列表
	 *
	 * @return array
	 */
	public static function getClassPath() {
		if (isset(self::$config["class-path"]) && is_array(self::$config["class-path"])) {
			return array_unique(array_merge(self::$config["class-path"], native::getDefaultPackages()));
		}
		else {
			return native::getDefaultPackages();
		}
	}
	
	/**
	 * 根据controller名称取得对应的类名称
	 *
	 * @param string $controllerName controller名称
	 * @return string
	 */
	public static function getControllerClass($controllerName) {
		$map = self::getControllerMap();
		if (isset($map[$controllerName])) {
			$config = $map[$controllerName];
			if (isset($config["class"])) {
				return $config["class"];
			}
		}
		return null;
	}
	
	/**
	 * 取得controller列表
	 *
	 * @return array
	 */
	public static function getControllerMap() {
		if (isset(self::$mvcConfig["controllers"])) {
			return self::$mvcConfig["controllers"];
		}
		return array();
	}
	
	/**
	 * 取得配置所在的目录
	 *
	 * @return string
	 */
	public static function getConfigDirectory() {
		return dirname(self::$configFile);
	}
	
	/**
	 * 取得错误报告级别
	 *
	 * @return integer
	 */
	public static function getErrorReportingLevel() {
		if (isset(self::$config["error-reporting"]["level"])) {
			return self::$config["error-reporting"]["level"];
		}
		return null;
	}
	
	/**
	 * 取得缓存配置
	 *
	 * @return array
	 */
	public static function getCacheConfig() {
		if (isset(self::$config["cache"])) {
			return self::$config["cache"];
		}
		return array();
	}
	
	/**
	 * 取得exception处理方式
	 *
	 * @return array
	 * @since 0.0.1
	 */
	public static function getExceptionHandlers() {
		if (isset(self::$config["exception-handler"])) {
			return self::$config["exception-handler"];
		}
		return array();
	}
	
	/**
	 * 处理值中的常量
	 *
	 * @param mixed $value 值
	 * @return string
	 */
	private static function parseValue($value) {
		$value = str_replace("%{IFRAMEWORK_DIRECTORY}", IFRAMEWORK_DIRECTORY, $value);
		$value = str_replace("%{IFRAMEWORK_APP_ROOT}", IFRAMEWORK_APP_ROOT, $value);
		return $value;
	}
	
	/**
	 * 添加选项
	 *
	 * @param string $name 选项名
	 * @param mixed $value 选项值
	 * @since 0.0.3
	 */
	public static function addOption($name, $value) {
		global $_CONFIG;
		if ($_CONFIG === null) {
			$_CONFIG = array();
		}
		if (!is_array($_CONFIG)) {
			throw new IException("global variable {\$_CONFIG} must be an array, but now is " . gettype($_CONFIG));
		}
		$_CONFIG[$name] = $value;
	}
	
	/**
	 * 取得用户配置
	 *
	 * @return array
	 * @since 0.2.1
	 */
	public static function getUserConfig() {
		global $_CONFIG;
		return $_CONFIG;
	}
	
	/**
	 * 加载MVC配置
	 *
	 * @param string $configFile 文件名
	 * @return array
	 * @since 0.0.3
	 */
	public static function loadMvc($configFile) {
		self::$mvcConfig = require($configFile);
		ILogger::debug("load mvc config from '{$configFile}'");
		if (!is_array(self::$mvcConfig)) {
			throw new IException("mvc config '{$configFile}' is invalid");
		}
		return self::$mvcConfig;
	}
	
	/**
	 * 取得MVC配置
	 *
	 * @return array
	 * @since 0.0.3
	 */
	public static function &getMvcConfig() {
		return self::$mvcConfig;
	}
	
	/**
	 * 加载配置文件
	 *
	 * @param string $configFile 配置文件
	 * @return array
	 * @since 0.0.3
	 */
	public static function load($configFile) {
		self::$configFile = $configFile;
		self::$config = require($configFile);
		
		//初始化
		if (isset(self::$config["date"])) {
			self::loadDateConfig(self::$config["date"]);
		}
		
		return self::$config;	
	}
	
	/**
	 * 取得应用配置
	 *
	 * @return array
	 * @since 0.2.1
	 */
	public static function &getAppConfig() {
		return self::$config;
	}
	
	/**
	 * 加载日期配置
	 *
	 * @param array $date 日期配置
	 */
	private static function loadDateConfig($date) {
		if (isset($date["timezone"])) {
			date_default_timezone_set($date["timezone"]);
		}
	}
	
	/**
	 * 取得控制器配置
	 *
	 * @param string $name 控制器名
	 * @return array
	 * @since 0.0.3
	 */
	public static function getControllerConfig($name) {
		if (isset(self::$mvcConfig["controllers"][$name])) {
			$info = self::$mvcConfig["controllers"][$name];
			if (isset($info["alias"])) {
				$aliasName = $info["alias"];
				if (isset(self::$mvcConfig["controllers"][$aliasName])) {
					$alias = self::$mvcConfig["controllers"][$aliasName];
					if (isset($alias["alias"]) && $alias["alias"] == $name) {
						throw new IException("bi-directional alias error between '{$name}' and '{$aliasName}'");
					}
					return self::getControllerConfig($aliasName);
				}
			}
			return $info;
		}
		return array();
	}
	
	/**
	 * 取得过滤器映射
	 *
	 * @return array
	 * @since 0.0.3
	 */
	public static function getFilterMapping() {
		if (isset(self::$mvcConfig["filter-mapping"])) {
			$array = self::$mvcConfig["filter-mapping"];
			if (is_array($array)) {
				return $array;
			}
		}
		return array();
	}
	
	/**
	 * 取得过滤器
	 *
	 * @param string $name 过滤器名称
	 * @return IFilter
	 * @since 0.0.3
	 */
	public static function getFilter($name) {
		if (isset(self::$mvcConfig["filters"])) {
			$filters = self::$mvcConfig["filters"];
			if (!isset($filters[$name]["class"])) {
				throw new IException("can't find class for '{$name}' filter");
			}
			$filter = IObjectFactory::getObject($filters[$name]["class"]);
			if ($filter == null) {
				throw new IException("can't find class '{$filters[$name]["class"]}'");
			}
			if (!($filter instanceof IFilter)) {
				throw new IException("{$filters[$name]["class"]} must be implements IFilter");
			}
			return $filter;
		}
		throw new IException("can't find class for '{$name}' filter");
	}
	
	/**
	 * 取得路由的配置
	 *
	 * @return array
	 * @since 0.0.3
	 */
	public static function getRouteConfig() {
		if (isset(self::$mvcConfig["route"])) {
			return self::$mvcConfig["route"];
		}
		return array();
	}
	
	/**
	 * 取得动作返回值配置
	 *
	 * @param string $controllerName 控制器名
	 * @param string $actionName 动作名
	 * @since 0.0.3
	 */
	public static function getReturnTypes($controllerName, $actionName) {
		if (isset(self::$mvcConfig["controllers"][$controllerName]["actions"][$actionName])) {
			$returnTypes = self::$mvcConfig["controllers"][$controllerName]["actions"][$actionName];
			if (!is_array($returnTypes)) {
				$returnTypes = array();
			}
			return $returnTypes;
		}
		return array();
	}
	
	/**
	 * 从一系列递进键中获取值
	 * 
	 * 比如： 
	 * 	getKeysValue($mvcConfig, "route.patterns.0")
	 * 可以获取
	 *  array(
	 *      "route" => array(
	 * 			"patterns" => array(
	 * 				0 => "my config"
	 * 			)
	 * 		)
	 *  )
	 * 中的 "my config"
	 *
	 * @param array $config 配置
	 * @param string $keys 键列表
	 * @return mixed
	 * @since 0.2.1
	 */
	public static function getKeysValue(array $config, $keys) {
		$keys = explode(".", $keys);
		if (count($keys) == 1) {
			return array_key_exists($keys[0], $config)?$config[$keys[0]]:null;
		}
		
		$lastKey = array_pop($keys);
		$lastArray = $config;
		foreach ($keys as $key) {
			if (is_array($lastArray) && array_key_exists($key, $lastArray)) {
				$lastArray = $lastArray[$key];
			}
			else {
				return null;
			}
		}
		
		return array_key_exists($lastKey, $lastArray)?$lastArray[$lastKey]:null; 
	}
	
	/**
	 * 设置递进键的值
	 *
	 * @param array $config 配置
	 * @param string $keys 键列表
	 * @param stirng $value 值
	 * @return boolean
	 * @since 0.2.1
	 */
	public static function setKeysValue(array &$config, $keys, $value) {
		$keys = explode(".", $keys);
		if (count($keys) == 1) {
			$config[$keys[0]] = $value;
			return true;
		}
		$lastKey = array_pop($keys);
		$lastConfig = &$config;
		foreach ($keys as $key) {
			if (!isset($lastConfig[$key]) || !is_array($lastConfig[$key])) {
				$lastConfig[$key] = array();
			}
			$lastConfig = &$lastConfig[$key];
		}
		$lastConfig[$lastKey] = $value;
		return true;
	}
}

?>